import DataBus from './databus.js'
import Player from './player.js'
import GameInfo from './gameinfo.js'
import Block from './block.js'
import Round from './round.js'
import Background from './background.js'
import Sprite from './base/sprite.js'
import Music from './music.js'

let databus = new DataBus()

// 获取全局 ctx 和 opendataContext
var ctx = canvas.getContext('2d')                                                                      
let openDataContext = wx.getOpenDataContext()


let onelinecount = 9 // 每行方块的个数

let blockCount = onelinecount*10 // 方块的总数 (gameinfo中需同步修改)

// 根据手机的高像素数来决定有多少方块儿
let ll = wx.getSystemInfoSync();
if (ll.windowHeight > 800){
  blockCount = onelinecount * 12
}


const CANVAS_WIDTH = canvas.width
const CANVAS_HEIGHT = canvas.height


// 创建广告
let bannerAd = wx.createBannerAd({
  adUnitId: 'adunit-a79a573ac1339350',
  style: {
    left: 0,
    top: CANVAS_HEIGHT - 115,
    height: 120,
    width: CANVAS_WIDTH
  }
});



let width = CANVAS_WIDTH / onelinecount


export default class Main{

  // 构造器
  constructor() {
    this.aniId = 0
    this.endTime == 0
    this.modeSelect()
    
    // 创建背景音乐
    this.music = new Music()

    // 每次进入小游戏的时候创建背景音乐并播放
    wx.onShow(function () {
      var music = new Music()
      music.bgmAudio.play()
    })
  }

  modeSelect(){
    // 1.移除绑定的 重新开始事件
    canvas.removeEventListener(
      'touchstart',
      this.againevent
    )

    // 2.清空画布
    ctx.clearRect(0, 0, canvas.width, canvas.height)

    // 加速垃圾回收
    wx.triggerGC()

    // 3.将数据发送到 开放数据域
    var data = {
      event: "readFriendData"
    }
    openDataContext.postMessage(data)

    // 4.进行索引渲染（排行榜、模式选择）
    this.renderIndex()

    // 5.添加模式选择点击事件
    this.modeevent = this.modeAreaTouchEventHandler.bind(this)
    canvas.addEventListener(
      'touchstart',
      this.modeevent
    )

  }

  /******************************************************************
   * 游戏重新开始
   */
  restart(mode){

    bannerAd = wx.createBannerAd({
      adUnitId: 'adunit-a79a573ac1339350',
      style: {
        left: 0,
        top: CANVAS_HEIGHT - 115,
        height: 120,
        width: CANVAS_WIDTH
      }
    });

    // 点击之后 移除 点击事件。
    canvas.removeEventListener(
      'touchstart',
      this.modeevent
    )

    // 清空数据
    databus.reset()
    _globalData.realTimeRank = []
    databus.mode = mode

    this.player = new Player(mode)
    this.gameinfo = new GameInfo()
    this.round = new Round()
    this.background = new Background()
    this.music = new Music()
    

    // 产生所有敌人敌人，放到 databus
    this.blockGenerate()
    this.bindLoop = this.loop.bind(this)
    this.hasEventBind = false

    
    // 清除上一局的动画
    window.cancelAnimationFrame(this.aniId);

    // 开始执行 loop
    this.startTime = new Date().getTime();
    this.aniId = 0
    this.aniId = window.requestAnimationFrame(
      this.bindLoop,
      canvas
    )
    
  }


  /**************************** 以下生产方块儿 ************************
   * 生产方块儿
   */
  randomColor() {
    switch (Math.round(Math.random() * 4)) {
      case 0:
        return '#cadca0';
      case 1:
        return '#dcd4a4';
      case 2:
        return '#87bac1';
      case 3:
        return '#f6c7c8';
      case 4:
        return '#af9dbb';
      default:
        return '#ec859b';
    }
  }
  randomSrc() {
    switch (Math.round(Math.random() * 4)) {
      case 0:
        return 'images/timgblue.png';
      case 1:
        return 'images/timgyellow.png';
      case 2:
        return 'images/timgred.png';
      case 3:
        return 'images/timgyak.png';
      case 4:
        return 'images/timgblue.png';
      default:
        return 'images/timgyellow.png';
    }
  }
  blockGenerate() {
    for (var i = 0; i < blockCount; i++) {

      var x = (i * width)
      if (i >= onelinecount) {
        x = i % onelinecount * width
      }
      var y = parseInt(i / onelinecount) * width
      new Block(onelinecount, x, y, this.randomColor(), this.randomSrc())
    }
  }

  


  


  /******************************* 以下为循环 loop **************************
   * 实现游戏帧循环
   */
  loop() {
    databus.frame++

    this.service()
    this.update()
    this.render()

    this.aniId = window.requestAnimationFrame(
      this.bindLoop,
      canvas
    )
  }


  /**************************** 以下为业务逻辑\更新\渲染 ************************
   * 其他业务逻辑
   */
  service() {
    // 游戏结束，不进行业务逻辑处理
    if (databus.gameOver) {
      return;
    }

    //120帧让后台广播一次
    if (databus.frame % 120 === 0) {
      this.gameinfo.sendScore(ctx, databus.score)
    }

    // 判断是否为街机模式
    if (databus.mode == 'crazy') {
      // 每隔200帧添加一行并降落
      if (databus.frame % 200 == 0) {
        // 1.移动之前所有的
        databus.block.forEach((temp) => {
          temp.y = temp.y + temp.height
        })
        // 2.新增一行
        for (var i = 0; i < onelinecount; i++) {
          var x = (i * width)
          var y = 0
          // 生成敌人，构造器会自动添加到 databus
          new Block(onelinecount, x, y, this.randomColor(), this.randomSrc())
        }

        this.judgeBlockOut()
      }
    }
  }


  /** 
   * 游戏逻辑更新主函数
   */
  update() {

    // 游戏结束，不进行更新位置
    if (databus.gameOver){
      return;
    }

    this.judgeCollepse()

    this.judgeScore()

  }


  /**
   * 渲染方法
   */
  render() {
    // 1.清空画布
    ctx.clearRect(0, 0, canvas.width, canvas.height)

    // 2.渲染背景图
    // this.background.drawToCanvas(ctx)

    // 创建渐变
    var grd = ctx.createLinearGradient(0, canvas.width, 0, 0);


    var mydate = new Date();
    var myddy = mydate.getDay(); //获取存储当前日期

    var weekday = ["7", "1", "2", "3", "4", "5", "6"];

    switch (parseInt(weekday[myddy])) {
      case 1:
        grd.addColorStop(0, "#a5dade");
        grd.addColorStop(1, "#a5dade");
        break;
      case 2:
        grd.addColorStop(0, "#e27b91");
        grd.addColorStop(1, "#e27b91");
        break;
      case 3:
        grd.addColorStop(0, "#faad33");
        grd.addColorStop(1, "#faad33");
        break;
      case 4:
        grd.addColorStop(0, "#3f8eb1");
        grd.addColorStop(1, "#3f8eb1");
        break;
      case 5:
        grd.addColorStop(0, "#cd9534");
        grd.addColorStop(1, "#cd9534");
        break;
      case 6:
        grd.addColorStop(0, "#c74c51");
        grd.addColorStop(1, "#c74c51");
        break;
      case 7:
        grd.addColorStop(0, "#c4d73b");
        grd.addColorStop(1, "#c4d73b");
        break;
      default:
        grd.addColorStop(0, "#2f93c2");
        grd.addColorStop(1, "#2f93c2");
        break;
    }


    

    // 填充渐变
    ctx.fillStyle = grd;
    ctx.fillRect(0, 0, canvas.width, canvas.height)

    // 3.渲染砖块儿
    databus.block.forEach((temp) => {
      var image = new Image()
      image.src = temp.src
      ctx.drawImage(image, temp.x, temp.y, temp.width, temp.height)
    })

    // 4.渲染托盘
    this.player.drawToCanvas(ctx)

    // 5.渲染小圆球
    this.round.drawToCanvas(ctx)

    // 6.渲染游戏得分
    this.gameinfo.renderGameScore(ctx, databus.score)

    databus.animations.forEach((ani) => {
      if (ani.isPlaying) {
        ani.aniRender(ctx)
      }
    })

    

    // 游戏结束停止帧循环
    if (databus.gameOver) {
      // 渲染游戏结束
      _globalData.score = databus.score + ""
      this.gameinfo.renderGameOver(ctx, _globalData.score, this.startTime)

      bannerAd.show();

      if (!this.hasEventBind) {
        // 没有绑定过事件
        this.hasEventBind = true

        // 1.播放结束声音
        this.music.playGameOver()

        // 3.绑定点击事件
        this.againevent = this.touchEventHandler.bind(this)
        canvas.addEventListener('touchstart', this.againevent)

        // 4.将结果写入 cloud
        this.saveScore()
      }

    }
  }




  /******************************* 以下为判断碰撞 **************************
   *  判断方块儿是否溢出
   */
  judgeBlockOut(){
    databus.block.forEach((temp) => {
      if(temp.y+temp.width >= CANVAS_HEIGHT-10){
        databus.gameOver = true
        return
      }
    })
  }

  /**
   * 判断圆球碰撞方块
   */
  judgeScore(){
    let count = 0
    databus.block.forEach((temp) => {
      count += 1

      // 如果距离超过 两倍的 temp.width,跳过下边的判断
      var long = 2 * temp.width
      if(Math.abs(this.round.x-temp.x) > long 
        && Math.abs(this.round.y - temp.y) > long ){
        return;
      }
      // 如果是在正下方(final)
      if (this.round.y < temp.y + temp.width 
      && this.round.y > temp.y + temp.width - this.round.width 
      && this.round.x > temp.x 
      && this.round.x < temp.width + temp.x-this.round.width/2){
        this.round.update(this.round.xFlag, -this.round.yFlag)
        this.music.playBlock()
        databus.block.splice(count-1, 1)
        databus.score += 1
        return
      }
      // 如果是在正上方
      if (this.round.y < temp.y
      && this.round.y > temp.y - this.round.width
      && this.round.x > temp.x 
      && this.round.x < temp.width + temp.x - this.round.width / 2) {
        this.round.update(this.round.xFlag, -this.round.yFlag)
        this.music.playBlock()
        databus.block.splice(count - 1, 1)
        databus.score += 1
        return
      }
      // 如果是在正右边
      if (this.round.y < temp.y + temp.width - this.round.width/2
      && this.round.y > temp.y 
      && this.round.x < temp.x + temp.width 
      && this.round.x > temp.x + temp.width-this.round.width){
        this.round.update(-this.round.xFlag, this.round.yFlag)
        this.music.playBlock()
        databus.block.splice(count-1, 1)
        databus.score += 1
        return
      }
      // 如果是在正左边
      if (this.round.y < temp.y + temp.width 
      && this.round.y > temp.y 
      && this.round.x + this.round.width < temp.x + this.round.width 
      && this.round.x + this.round.width > temp.x) {
        this.round.update(-this.round.xFlag, this.round.yFlag)
        this.music.playBlock()
        databus.block.splice(count-1, 1)
        databus.score += 1
        return
      }
    })
    if (databus.block.length == 0){
      databus.gameOver = true
    }
  }

  // 判断圆球碰撞边框和托盘
  judgeCollepse(){
    // 小圆球撞击屏幕左右两边
    if (this.round.x < 0 
    || CANVAS_WIDTH - this.round.width/2 < this.round.x){
      //（x 速度反向）
      this.round.update(-this.round.xFlag, this.round.yFlag)
      return
    }
    // 小圆球撞击屏幕顶部
    if (this.round.y < -this.round.width/2){
      // （y 速度反向）
      this.round.update(this.round.xFlag, -this.round.yFlag)
      return
    }
    // 小圆球撞击托盘
    if (this.round.y + this.round.width < this.player.y + this.round.width && this.round.y + this.round.width > this.player.y && this.round.x > this.player.x && this.round.x < this.player.x + this.player.PLAYER_WIDTH){
      //（y 速度反向）
      this.music.playPlayer()
      this.round.update(this.round.xFlag, - this.round.speed)
      return
    }
    // 到屏幕底部
    if (CANVAS_HEIGHT - this.round.y < this.round.width 
    && (this.round.x < this.player.x 
        || this.round.x > (this.player.x + this.player.PLAYER_WIDTH)) ){
      //（游戏结束）
      databus.gameOver = true
      return
    }
    // 修改小圆球的信息
    this.round.update(this.round.xFlag, this.round.yFlag)
  }








  /******************************* 以下为点击事件 **************************
   * 游戏结束后重新开始 -点击事件
   */
  touchEventHandler(e) {
    e.preventDefault()

    // 触摸位置坐标
    let x = e.touches[0].clientX
    let y = e.touches[0].clientY

    let area = this.gameinfo.btnArea

    // 如果触摸到重新开始按钮区域。 重启游戏。
    if (x >= area.startX
      && x <= area.endX
      && y >= area.startY
      && y <= area.endY) {

      // 清除上一次局动画
      window.cancelAnimationFrame(this.aniId);

      // 播放音乐
      this.music.playAgain()

      // 重新开始
      this.modeSelect()

      bannerAd.hide();
    }
  }


  /**
   * 选择模式-点击事件
   */
  modeAreaTouchEventHandler(e) {
    
    e.preventDefault()
    // 点击的坐标
    let x = e.touches[0].clientX
    let y = e.touches[0].clientY

    // 如果触摸到重新开始按钮区域。 重启游戏。
    let nomalarea = this.nomalModeArea
    if (x >= nomalarea.startX
      && x <= nomalarea.endX
      && y >= nomalarea.startY
      && y <= nomalarea.endY) {
      
      // 播放声音
      this.music.playSelect()

      // 设置模式
      databus.mode = 'nomal'

      // 清空画布
      ctx.clearRect(0, 0, canvas.width, canvas.height)

      // 重启
      this.restart('nomal')
    }

    // 如果触摸到街机模式按钮区域。 重启游戏。
    let crazyarea = this.crazyModeArea
    if (x >= crazyarea.startX
      && x <= crazyarea.endX
      && y >= crazyarea.startY
      && y <= crazyarea.endY) {

      // 播放声音
      this.music.playSelect()

      // 设置模式
      databus.mode = 'crazy'

      // 清空画布
      ctx.clearRect(0, 0, canvas.width, canvas.height)

      // 重启
      this.restart(databus.mode)
    }
  }


  /******************************************************************************
   * 渲染索引页
   */
  renderIndex(){
    
    var halfWidth = CANVAS_WIDTH / 2

    // index 页面背景图
    var image = new Image()
    image.onload = function () {
      // 绘制头像大图和 shared 画布 半秒钟等待shared 画布的绘制过程。
      setTimeout(function () {
        ctx.drawImage(image, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT - halfWidth)
        let sharedCanvas = openDataContext.canvas
        ctx.drawImage(sharedCanvas, 0, 0)
      }, 600)
    }
    image.src = _globalData.userInfo.avatarUrl

    // 绘制蓝色方框
    ctx.fillStyle = "#aab8a4"
    ctx.fillRect(0, CANVAS_HEIGHT - halfWidth, halfWidth, halfWidth)
    ctx.fillStyle = "#FFFFFF"
    ctx.font = "20px Arial"
    
    ctx.fillText('普通模式',
      (halfWidth - 80)/2,
      CANVAS_HEIGHT - halfWidth + halfWidth / 2 - 5
    )
    // 指定范围
    this.nomalModeArea = {
      startX: 0,
      endX: halfWidth,
      startY: CANVAS_HEIGHT - halfWidth,
      endY: CANVAS_HEIGHT
    }

    // 绘制黄色方框
    ctx.fillStyle = "#ef7c6a"
    ctx.fillRect(halfWidth, CANVAS_HEIGHT - halfWidth, halfWidth, halfWidth)
    ctx.fillStyle = "#FFFFFF"
    ctx.font = "20px Arial"
    ctx.fillText('街机模式',
      (halfWidth - 80) / 2 + halfWidth,
      CANVAS_HEIGHT - halfWidth + halfWidth / 2 - 5
    )
    // 指定范围
    this.crazyModeArea = {
      startX: halfWidth,
      endX: CANVAS_WIDTH,
      startY: CANVAS_HEIGHT - halfWidth,
      endY: CANVAS_HEIGHT
    }
  }

  /**********************************************************************************
   * 保存得分
   */
  saveScore(){
    var kvDataList = new Array();
    var setCloudData = {
      key: "score",
      value: _globalData.score
    }
    kvDataList.push(setCloudData);

    var data = {
      event: "write",
      KvDataList: kvDataList
    }
    openDataContext.postMessage(data)

  }


}